package edu.upenn.cis.cis555.webserver;

import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Set;
import java.util.Vector;
import java.util.regex.Pattern;

import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class ServletContext implements javax.servlet.ServletContext {
	
	private HashMap<String,Object> attributes;
	private HashMap<String,String> initParams;
	
	public ServletContext() {
		attributes = new HashMap<String,Object>();
		initParams = new HashMap<String,String>();
	}
	
	void setInitParam(String name, String value) {
		initParams.put(name, value);
	}

	@Override //DONE
	public Object getAttribute(String name) {
		// Returns the servlet container attribute with the given name, or null if there is no attribute by that name.
		if (!attributes.containsKey(name))
			return null;
		return attributes.get(name);
	}

	@Override //DONE
	public Enumeration<String> getAttributeNames() {
		// Returns an Enumeration containing the attribute names available within this servlet context.
		Set<String> keys = attributes.keySet();
		Vector<String> atts = new Vector<String>(keys);
		return atts.elements();
	}

	@Override //DONE
	public ServletContext getContext(String uripath) {
//	    Returns a ServletContext object that corresponds to a specified URL on the server.
//
//	    This method allows servlets to gain access to the context for various parts of the server, and as 
//		needed obtain RequestDispatcher objects from the context. The given path must be begin with "/", is 
//		interpreted relative to the server's document root and is matched against the context roots of other 
//		web applications hosted on this container.
//
//	    In a security conscious environment, the servlet container may return null for a given URL.
//
//	    Parameters:
//	        uripath - a String specifying the context path of another web application in the container. 
//	    Returns:
//	        the ServletContext object that corresponds to the named URL, or null if either none exists 
//		or the container wishes to restrict this access.
		Pattern p1 = Pattern.compile("/");
		String[] result1 = p1.split(uripath);
		HttpServlet servlet = HttpServer.servlets.get(result1[1]);
		if (servlet != null)
			return (ServletContext) servlet.getServletContext();
		else
			return null;
	}

	@Override //DONE
	public String getInitParameter(String name) {
		// Returns a String containing the value of the named context-wide initialization parameter, 
		// or null if the parameter does not exist
		if (!initParams.containsKey(name))
			return null;
		return initParams.get(name);
	}

	@Override //DONE
	public Enumeration<String> getInitParameterNames() {
		// Returns the names of the context's initialization parameters as an Enumeration of String objects, 
		// or an empty Enumeration if the context has no initialization parameters.
		Set<String> keys = initParams.keySet();
		Vector<String> atts = new Vector<String>(keys);
		return atts.elements();
	}

	@Override //DONE
	public String getRealPath(String path) {
//		Returns a String containing the real path for a given virtual path. For example, the path "/index.html" returns the 
//		absolute file path on the server's filesystem would be served by a request for "http://host/contextPath/index.html", 
//		where contextPath is the context path of this ServletContext..
//
//		The real path returned will be in a form appropriate to the computer and operating system on which the servlet container 
//		is running, including the proper path separators. This method returns null if the servlet container cannot translate the 
//		virtual path to a real path for any reason (such as when the content is being made available from a .war archive).
		try {
			StringBuffer temp = new StringBuffer(path);
			temp.insert(0, new String(HttpServer.root_path));
			File reqfile = new File(temp.toString());
			return reqfile.getCanonicalPath();
		} catch (Exception e) {
			HttpServer.logError("getRealPath() error " + e.getMessage());
			return null;	
		}
	}

	@Override //DONE
	public String getServerInfo() {
		// Returns the name and version of the servlet container on which the servlet is running.
		return "StuServletContainer Version 3.46";
	}

	@Override //DONE
	public String getServletContextName() {
//	    Returns the name of this web application corresponding to this ServletContext as specified in the deployment 
//	    descriptor for this web application by the display-name element.
//
//	    Returns:
//	        The name of the web application or null if no name has been declared in the deployment descriptor.
		return HttpServer.servletAppName;
	}


	@Override //DONE
	public void removeAttribute(String name) {
//		Removes the attribute with the given name from the servlet context. After removal, subsequent 
//		calls to getAttribute(java.lang.String) to retrieve the attribute's value will return null.
//
//		If listeners are configured on the ServletContext the container notifies them accordingly. 
		attributes.remove(name);
	}

	@Override //DONE
	public void setAttribute(String name, Object object) {
//		Binds an object to a given attribute name in this servlet context. If the name specified is already used for an 
//		attribute, this method will replace the attribute with the new to the new attribute.
//
//		If listeners are configured on the ServletContext the container notifies them accordingly.
//
//		If a null value is passed, the effect is the same as calling removeAttribute().
//
//		Attribute names should follow the same convention as package names. The Java Servlet API specification reserves 
//		names matching java.*, javax.*, and sun.*
		if (object == null)
			removeAttribute(name);
		else
			attributes.put(name, object);
	}
	
	@Override //DONE
	public int getMajorVersion() {
		// Returns the major version of the Java Servlet API that this servlet container supports. 
		// All implementations that comply with Version 2.4 must have this method return the integer 2.
		return 2;
	}

	@Override //DONE
	public int getMinorVersion() {
		// Returns the minor version of the Servlet API that this servlet container supports. 
		// All implementations that comply with Version 2.4 must have this method return the integer 4. 
		return 4;
	}
	
	@Override //DONE
	public Enumeration<?> getServletNames() {
		// Deprecated. As of Java Servlet API 2.1, with no replacement. 
		return null;
	}

	@Override //DONE
	public Enumeration<?> getServlets() {
		// Deprecated. As of Java Servlet API 2.0, with no replacement. 
		return null;
	}
	
	@Override //DONE
	public Servlet getServlet(String name) throws ServletException {
		// Deprecated. As of Java Servlet API 2.1, with no direct replacement. 
		return null;
	}
	
	@Override //DONE
	public void log(String msg) {
		//System.err.println(msg);
	}

	@Override //DONE
	public void log(Exception exception, String msg) {
		//log(msg, (Throwable) exception);
	}

	@Override //DONE
	public void log(String message, Throwable throwable) {
		//System.err.println(message);
		//throwable.printStackTrace(System.err);
	}
	
	@Override //DONE
	public String getMimeType(String file) {
		return null;
	}
	
	@Override //DONE
	public RequestDispatcher getNamedDispatcher(String name) {
		return null;
	}
	
	@Override //DONE
	public URL getResource(String path) throws MalformedURLException {
		return null;
	}

	@Override //DONE
	public InputStream getResourceAsStream(String path) {
		return null;
	}

	@Override //DONE
	public Set<?> getResourcePaths(String path) {
		return null;
	}
	
	@Override //DONE
	public RequestDispatcher getRequestDispatcher(String name) {
		return null;
	}

}
